package org.easystub.dbstub;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

public class TableBuilder {

    private final String tableName;
    private final Map<String, Column> columns;
    private final String schema;
    private Connection connection;
    private PrimaryKey primaryKey;

    public TableBuilder(String tableName, Connection connection, String schema) throws SQLException {
        this(tableName, connection, null, schema);
    }

    public TableBuilder(String tableName, Connection connection, PrimaryKey primaryKey, String schema) {
        this.tableName = tableName;
        this.connection = connection;
        this.columns = new LinkedHashMap<String, Column>();
        this.primaryKey = primaryKey;
        this.schema = schema;
    }

    public TableBuilder addColumn(String columnName, SqlType sqlType) {
        columns.put(columnName, new Column(sqlType));
        return this;
    }

    public TableBuilder addColumn(String columnName, SqlType sqlType, Integer columnSize) {
        columns.put(columnName, new Column(sqlType, columnSize));
        return this;
    }

    public void build() {
        StringBuilder builder = new StringBuilder();
        builder.append("create table ");
        builder.append(schema);
        builder.append(".");
        builder.append(tableName);
        builder.append("(");

        if(primaryKey != null) {
            builder.append(buildPrimaryKey());
        }

        for(Map.Entry<String, Column> column : columns.entrySet()) {
            builder.append(" ");
            builder.append(column.getKey());
            builder.append(" ");
            builder.append(column.getValue().sqlType);
            if(column.getValue().size != null) {
                builder.append("(");
                builder.append(column.getValue().size);
                builder.append(") ");
            }
            builder.append(",");
        }

        builder.deleteCharAt(builder.length() - 1);
        builder.append(")");

        try {
            connection.prepareStatement(builder.toString()).execute();
        } catch(SQLException e) {
            throw new DBStubException(e);
        }
    }

    private String buildPrimaryKey() {
        StringBuilder primaryKeySql = new StringBuilder();
        primaryKeySql.append(primaryKey.getColumnName());
        primaryKeySql.append(" ");
        primaryKeySql.append(primaryKey.getSqlType());

        if(Autogenerate.BY_DEFAULT == primaryKey.getAutogenerate()) {
            primaryKeySql.append(" generated by default as identity (start with 1)");
        } else {
            primaryKeySql.append(" primary key");
        }

        if(!columns.isEmpty()) {
            primaryKeySql.append(",");
        }
        
        return primaryKeySql.toString();
    }

    private class Column {
        private final SqlType sqlType;
        private final Integer size;

        private Column(SqlType sqlType, Integer size) {
            this.sqlType = sqlType;
            this.size = size;
        }

        private Column(SqlType sqlType) {
            this(sqlType, null);
        }
    }
}
